home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume6 / gone-2.0 < prev    next >
Encoding:
Text File  |  1989-04-08  |  32.9 KB  |  1,173 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. Subject: v06i086: Gone version 2.0: vt[12]?? terminal locking program
  4. Organization: Samsung Software America, Inc.
  5. Reply-To: lavallee@samsung.com (Warren Lavallee)
  6.  
  7. Posting-number: Volume 6, Issue 86
  8. Submitted-by: lavallee@samsung.com (Warren Lavallee)
  9. Archive-name: gone-2.0
  10.  
  11.     This is gone v2.0.  An earlier version was posted previously about
  12. a year or so ago.  This is basically a lock for vt[12]xx terminals that
  13. looks nicer than lock.  This will probally be of no use to you at all
  14. unless you have a true vt[12]xx compatible terminal.
  15.  
  16.     A few new features have been added since the last release:
  17.  
  18.     o ~/.passwd file.  On some systems, passwd's are not kept in
  19.         /etc/passwd.  On these systems, gone can create and use
  20.         it's own crypted passwd found in this file.  See man page
  21.         for option.
  22.  
  23.     o timeout.  Gone now timesout.  This is configurable in conf.h
  24.  
  25.     o Support for Pyramid computers has been added.
  26.  
  27.     o Added error checking.
  28.  
  29.     This has successfully compiled under Ultrix 2.x, BSD 4.3, DGUX 3.00, 
  30.     Dynix 2.1, Dynix 3.0, Sun OS 4.0, and DualPort OS 4.4b
  31.  
  32. #! /bin/sh
  33. # This is a shell archive.  Remove anything before this line, then unpack
  34. # it by saving it into a file and typing "sh file".  To overwrite existing
  35. # files, type "sh file -c".  You can also feed this as standard input via
  36. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  37. # will see the following message at the end:
  38. #        "End of archive 1 (of 1)."
  39. # Contents:  Makefile README conf.h gone.1l gone.c
  40. # Wrapped by lavallee@ginosko on Fri Apr  7 14:19:57 1989
  41. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  42. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  43.   echo shar: Will not clobber existing file \"'Makefile'\"
  44. else
  45. echo shar: Extracting \"'Makefile'\" \(761 characters\)
  46. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  47. X# This  software  is provided with absolutely no warranty, to the extent
  48. X# permitted  by  applicable  state law.  In no event, unless required by
  49. X# applicable law, will the author(s) of this this software be liable for
  50. X# any damages caused by this software.
  51. X#
  52. all: gone gone.man
  53. X
  54. gone: gone.c conf.h
  55. X    cc -O -o gone gone.c
  56. X
  57. gone.man: gone.1l
  58. X    nroff -man gone.1l > gone.man
  59. X
  60. clean:
  61. X    /bin/rm -f *.o gone *~ foo bar baz Gone?? gone.man
  62. X
  63. shar: Gone01
  64. X
  65. Gone01: conf.h Makefile gone.c gone.1l README
  66. X    makekit -nGone Makefile README conf.h gone.c gone.1l 
  67. X
  68. install: gone gone.1l
  69. X    cp gone /usr/local/bin/gone
  70. X    chgrp kmem /usr/local/bin/gone
  71. X    chmod 2755 /usr/local/bin/gone
  72. X    cp gone.1l /usr/man/manl
  73. X
  74. gone.c: conf.h Makefile
  75. Gone01: conf.h Makefile gone.c gone.1l README
  76. END_OF_FILE
  77. if test 761 -ne `wc -c <'Makefile'`; then
  78.     echo shar: \"'Makefile'\" unpacked with wrong size!
  79. fi
  80. # end of 'Makefile'
  81. fi
  82. if test -f 'README' -a "${1}" != "-c" ; then 
  83.   echo shar: Will not clobber existing file \"'README'\"
  84. else
  85. echo shar: Extracting \"'README'\" \(1040 characters\)
  86. sed "s/^X//" >'README' <<'END_OF_FILE'
  87. X
  88. X    This is gone v2.0.  An earlier version was posted previously about
  89. a year or so ago.  This is basically a lock for vt[12]xx terminals that
  90. looks nicer than lock.  This will probally be of no use to you at all
  91. unless you have a true vt[12]xx compatible terminal.
  92. X
  93. X    A few new features have been added since the last release:
  94. X
  95. X    o ~/.passwd file.  On some systems, passwd's are not kept in
  96. X        /etc/passwd.  On these systems, gone can create and use
  97. X        it's own crypted passwd found in this file.  See man page
  98. X        for option.
  99. X
  100. X    o timeout.  Gone now timesout.  This is configurable in conf.h
  101. X
  102. X    o Support for Pyramid computers has been added.
  103. X
  104. X    o Added error checking.
  105. X
  106. X    This has successfully compiled under Ultrix 2.x, BSD 4.3, DGUX 3.00, 
  107. X    Dynix 2.1, Dynix 3.0, Sun OS 4.0, and DualPort OS 4.4b
  108. X
  109. X----------------------------------------------------------------------------
  110. INTERNET:  lavallee@samsung.com
  111. UUCP:      {decvax!{gsg,cg-atla},uunet,ulowell}!ginosko!lavallee
  112. US MAIL:   Samsung Software America. One Corporate Dr.  Andover, Ma.  01810
  113. END_OF_FILE
  114. if test 1040 -ne `wc -c <'README'`; then
  115.     echo shar: \"'README'\" unpacked with wrong size!
  116. fi
  117. # end of 'README'
  118. fi
  119. if test -f 'conf.h' -a "${1}" != "-c" ; then 
  120.   echo shar: Will not clobber existing file \"'conf.h'\"
  121. else
  122. echo shar: Extracting \"'conf.h'\" \(1051 characters\)
  123. sed "s/^X//" >'conf.h' <<'END_OF_FILE'
  124. X/* This  software  is provided with absolutely no warranty, to the extent
  125. X * permitted  by  applicable  state law.  In no event, unless required by
  126. X * applicable law, will the author(s) of this this software be liable for
  127. X * any damages caused by this software.
  128. X */
  129. X
  130. X#ifndef __CONF__
  131. X#define VERSION "2.0"
  132. X
  133. X/** undefine TIMEOUT if you want no timeout **/
  134. X
  135. X#define TIMEOUT 60        /** default timeout          **/
  136. X#define MAXTIMEOUT 180        /** Maximum timeout allowed. **/
  137. X#undef HOSTNAME            /** define this to you hostname if
  138. X                 **  you don't have gethostname(2)
  139. X                 **/
  140. X
  141. X/**         You may undefine this if you don't want it                 **/
  142. X
  143. X#define WIZGROUP "wheel"    /** Magic group:
  144. X                              * If you type in the password of someone
  145. X                  * in this group, you will get out.
  146. X                  *
  147. X                  * I think this is better than having a
  148. X                  * global password like "hasta la vista"
  149. X                  * like some locks have.
  150. X                 **/
  151. X
  152. X/** #define FCRYPT **/         /** define if you are useing fcrypt **/
  153. X
  154. X#define __CONF__
  155. X#endif
  156. END_OF_FILE
  157. if test 1051 -ne `wc -c <'conf.h'`; then
  158.     echo shar: \"'conf.h'\" unpacked with wrong size!
  159. fi
  160. # end of 'conf.h'
  161. fi
  162. if test -f 'gone.1l' -a "${1}" != "-c" ; then 
  163.   echo shar: Will not clobber existing file \"'gone.1l'\"
  164. else
  165. echo shar: Extracting \"'gone.1l'\" \(1545 characters\)
  166. sed "s/^X//" >'gone.1l' <<'END_OF_FILE'
  167. X.TH GONE "1 local" "AJR/WJL"
  168. X.SH NAME
  169. gone [\-t number] [\-c] [\-p] \- reserve a terminal
  170. X.SH SYNOPSIS
  171. X.B gone 
  172. X.SH DESCRIPTION
  173. X.IR Gone
  174. clears the screen and prints a cute picture on the display.  It
  175. then asks you for a Magic Word.  The Magic Word is the password
  176. you use to log on to the system.  You must type this in to exit
  177. gone.  Gone will display the load average and the number of users
  178. that are on the system near the bottom of the screen.  This info
  179. will be updated every minute.
  180. X.SH OPTIONS
  181. X.PP
  182. The
  183. X.IR \-t
  184. flag allows you to change the timeout interval.  The default interval is
  185. X20 minutes.  The maximum interval is defined at compile time and defaults
  186. to 45 minutes.
  187. X.PP
  188. The 
  189. X.IR \-c
  190. flag allows you to initialize/change a password in ~/.passwd.  Some
  191. versions of UNIX don't keep encrypted passwords in /etc/passwd anymore.
  192. On these systems, you can keep and encrypted password in ~/.passwd for
  193. gone.
  194. X.PP
  195. The
  196. X.IR \-p
  197. flag is present to let you defeat idle daemons and things like that.  It
  198. touches the terminal every five minutes.  This feature is only supported
  199. on a smart terminal due to implementation details.
  200. X.SH INSPIRATION
  201. X.IR Gone
  202. was written because using lock was too time consuming.  With
  203. X.IR gone
  204. all you have to do is type in gone and you are done. 
  205. The escape sequences were snagged from a
  206. X.IR VMS 
  207. COM file and converted to 
  208. X.IR UNIX
  209. gone.
  210. X.SH AUTHORS
  211. Warren Lavallee (converted it to C), 
  212. Andy Rosen  (provided DG/UX code so it would work on DG/UX systems)
  213. X.SH ADDRESS
  214. X    lavallee@samsung.com
  215. X    arosen@hawk.ulowell.edu
  216. END_OF_FILE
  217. if test 1545 -ne `wc -c <'gone.1l'`; then
  218.     echo shar: \"'gone.1l'\" unpacked with wrong size!
  219. fi
  220. # end of 'gone.1l'
  221. fi
  222. if test -f 'gone.c' -a "${1}" != "-c" ; then 
  223.   echo shar: Will not clobber existing file \"'gone.c'\"
  224. else
  225. echo shar: Extracting \"'gone.c'\" \(24387 characters\)
  226. sed "s/^X//" >'gone.c' <<'END_OF_FILE'
  227. static char *credits="@(#) GONE Version 2.0--(c)1989 Warren Lavallee/Andrew Rosen\n";
  228. X
  229. static char *authors = "@(#)Warren Lavallee, Andy Rosen";
  230. X
  231. X/*
  232. X * All rights reserved with the following exceptions
  233. X * 
  234. X * This software is supplied free of charge.  This software, or any part
  235. X * of it, may  not  be  redistributed or otherwise made available to, or
  236. X * used  by, any  other  person  without the inclusion of this copyright
  237. X * notice.  This software may not be used to make a profit in any way.
  238. X * 
  239. X * This  software  is provided with absolutely no warranty, to the extent
  240. X * permitted  by  applicable  state law.  In no event, unless required by
  241. X * applicable law, will the author(s) of this this software be liable for
  242. X * any damages caused by this software.
  243. X * 
  244. X * This will compile under Ultrix 2.x, BSD 4.3, DGUX 3.00, 
  245. X *   Dynix 2.1, Dynix 3.0, Sun OS 4.0, DualPort OS 4.4b
  246. X */
  247. X
  248. X/**
  249. X *  C program by Warren Lavallee
  250. X *  DGUX code by Andy Rosen
  251. X **/
  252. X
  253. X#include <stdio.h>
  254. X#include <syslog.h>
  255. X#include <sys/types.h>
  256. X#include <sys/stat.h>
  257. X#include <signal.h>
  258. X#include <pwd.h>
  259. X#include <sys/file.h>
  260. X#include <utmp.h>
  261. X#include <nlist.h>
  262. X#include <time.h>
  263. X#include <sgtty.h>
  264. X#include <grp.h>
  265. X#include <assert.h>
  266. X
  267. X#include "conf.h"
  268. X
  269. X#ifdef FCRYPT
  270. X#define CRYPT fcrypt        /** Use the fast crypt (not incl)**/
  271. char *fcrypt ();
  272. X#else
  273. char *crypt ();
  274. X#define CRYPT crypt        /** Use library crypt  **/
  275. X#endif
  276. X
  277. X#ifdef UENT
  278. X#include <uent.h>
  279. X#endif
  280. X
  281. X#ifdef dgux
  282. X#include <fcntl.h>
  283. X#endif
  284. X
  285. typedef enum {false, true} bool;
  286. X
  287. char *getenv(), *getpass(), *ttyname(), *strcpy();
  288. char savehost[28];
  289. double load();
  290. long startup_time;        /** Time we started up                   **/
  291. X#ifdef TIMEOUT
  292. long timeouttime = TIMEOUT;
  293. X#endif
  294. X
  295. int die(),            /** Exits                             **/
  296. X    pflag = 0,             /** Touch the terminal evey 5 minutes    **/
  297. X    dflag = 0,             /** Want to use dumb format anyways?     **/
  298. X    pid,             /** Used with fork                 **/
  299. X    invalid = 0,        /** Number of invalid logins             **/
  300. X    foo,                        /** Generic tmp variable                 **/
  301. X    dumb;            /** Am I dumb?                     **/
  302. X
  303. bool virgin = true;         /** Am I a virgin?                 **/
  304. X
  305. struct passwd *pwd;        /** Used to find next variable (myname)  **/
  306. char myname[9];            /** Who am i?                     **/
  307. char hostname[28];        /** Where am i?                     **/
  308. char *validate();        /** Is this password valid?             **/
  309. X
  310. struct unode {                  /** In here goes the encrypted passwords **/
  311. X  char name[81];                /**  of all the people in WIZGROUP.      **/
  312. X  char passwd[20];              /** Faster this way, instead of scanning **/
  313. X  struct unode *next;           /**  the whole password file each time   **/
  314. X} *wizusers = NULL;             /**  a password is typed in.             **/
  315. X
  316. X#ifdef UENT            /** Local: We store names and ss#'s for  **/
  317. struct uent muent;        /**   each person.             **/
  318. X#endif
  319. X
  320. X#ifdef TIMEOUT
  321. int timeout ();            /** Jump to here if we get a SIGALRM     **/
  322. X#endif
  323. X
  324. char *mcrypt();                 /** My crypt.  Decides whether to use    **
  325. X                                 **  the fast crypt, or the library      **
  326. X                 **  crypt                 **
  327. X                 **                                      **/
  328. X
  329. struct passwd *getpwuid();    /** Just in case pwd.h didn't declare it
  330. X                 **/
  331. main(argc, argv)
  332. X     int argc;
  333. X     char *argv[];
  334. X{
  335. X  register i = 1;
  336. X  int intprint();
  337. X  char *obuf = (char *) malloc (80L*25L);/** stdout buffer/one full screen**/
  338. X  char *term = getenv("TERM");         /** Terminal type                **/
  339. X  char *liberator = NULL;         /** Who liberated this terminal? **/
  340. X
  341. X  for (i = SIGHUP; i <= SIGUSR2; i++)
  342. X    signal(i, intprint);
  343. X
  344. X  (void) signal(SIGINT, SIG_IGN);
  345. X  (void) signal(SIGQUIT, SIG_IGN);
  346. X#ifdef SIGTSTP    /** Some sysVers don't have job control. **/
  347. X  (void) signal(SIGTSTP, SIG_IGN);
  348. X#endif
  349. X#ifdef SIGTTOU  /** Bug in kernel with pgrps can send this signal. **/
  350. X  (void) signal(SIGTTOU, SIG_IGN);
  351. X#endif
  352. X  (void) signal(SIGTERM, die);
  353. X  (void) signal(SIGCHLD, SIG_DFL);
  354. X#ifdef TIMEOUT
  355. X  (void) signal(SIGALRM, timeout);
  356. X#endif
  357. X  
  358. X  if (!isatty(0)) {               /** pipes?  ICK                   **/
  359. X     fprintf(stderr, 
  360. X       "%s: Without a terminal?  What\'s the point\?\n", argv[0]);
  361. X     exit(-1);
  362. X  } else if (!strcmp(term, "emacs")) {     /** In emacs window            **/
  363. X     fprintf(stderr,            /** I guess we get all types       **/
  364. X       "%s: In an emacs window?  Ha\!\n", argv[0]);
  365. X     exit(-1);
  366. X  } else if (!strncmp(term, "xterm", 5)) { /** an X window?  Gaud, get real **/
  367. X     fprintf(stderr, "In an X-window?  Be real.\n");
  368. X     fprintf(stderr, "Try xlock instead l\buser.\n");
  369. X     exit(-1);
  370. X  } else {                  /** In script, or a window, come on, be real!  **/
  371. X#ifdef unix
  372. X     char *name = (char *) getlogin ();
  373. X#else
  374. X     char *name = (char *) cuserid(NULL);
  375. X#endif
  376. X
  377. X     if (strlen(name) < 2) {         /** Not logged in on terminal      **/
  378. X        fprintf(stderr,            /** Must be in script or something **/
  379. X          "%s: You must be at the lowest level to run gone.\n", argv[0]);
  380. X    fprintf(stderr,
  381. X      "%s:  i.e.. on your login terminal, and in your login shell.\n",
  382. X        argv[0]);
  383. X        exit(-1);
  384. X     }
  385. X  }
  386. X
  387. X  setbuf (stdout, obuf);
  388. X#ifdef FCRYPT
  389. X  init_des ();
  390. X#endif
  391. X
  392. X#ifdef dgux
  393. X  assert(1);                /** Just checking                **/
  394. X#endif
  395. X
  396. X#ifdef UENT
  397. X  muent = getuent(getuid());
  398. X#endif
  399. X
  400. X  while ((i <= argc-1) && (argv[i++][0] == '-')) {
  401. X    switch (argv[i-1][1]) {
  402. X    case 'p': 
  403. X      ++pflag;
  404. X      break;
  405. X#ifdef TIMEOUT
  406. X    case 't':
  407. X      timeouttime = atoi(argv[i++]);
  408. X      break;
  409. X#endif
  410. X    case 'd': 
  411. X      ++dflag;
  412. X      break;
  413. X    case 'c': { /** Change the password in the ~/.passwd file or create one **/
  414. X      struct passwd *pwd;
  415. X      FILE *pwdfile;
  416. X      char path[80], *chpasswd();
  417. X      char oldpw[12], newpw[12];
  418. X      
  419. X      if ((pwd = getpwuid(getuid())) == NULL) {
  420. X    printf("Intruder alert!?\n");
  421. X    printf("Your account appears to be GONE.\n");
  422. X    exit(1);
  423. X      }
  424. X      sprintf(path, "%s/.passwd", pwd->pw_dir);
  425. X      if ((pwdfile = fopen(path, "r")) == NULL) {
  426. X    strcpy(oldpw, "");
  427. X      } else {
  428. X    fscanf(pwdfile, "%s", oldpw);
  429. X    fclose(pwdfile);
  430. X      }
  431. X
  432. X      strcpy(newpw, chpasswd(oldpw));
  433. X      sprintf(path, "%s/.passwd", pwd->pw_dir);
  434. X      if ((pwdfile = fopen(path, "w+")) == NULL) {
  435. X    fprintf(stderr, 
  436. X        "cannot change passwd, open of .passwd file failed.\n");
  437. X    perror(path);
  438. X    exit(1);
  439. X      }
  440. X      fprintf(pwdfile, "%s\n", newpw);
  441. X      fclose(pwdfile);
  442. X      exit(1);
  443. X      }
  444. X    default: 
  445. X      fprintf(stderr, "%s:  Can\'t grok a %c\n", argv[0], argv[i-1][1]);
  446. X      sleep (1);
  447. X      break;
  448. X    }
  449. X  }
  450. X#ifdef TIMEOUT
  451. X  if (!wizuser())
  452. X    if (timeouttime > MAXTIMEOUT) {
  453. X      timeouttime = MAXTIMEOUT;
  454. X      fprintf(stderr, "Maximum time out is %d.\n", MAXTIMEOUT);
  455. X      fprintf(stderr, "You request has been degraded to that amount.\n");
  456. X    } else 
  457. X      if (timeouttime < 1) {
  458. X    timeouttime = TIMEOUT;
  459. X    fprintf(stderr, "Timeout times must be greater and not equal to 0 minutes.\n");
  460. X      }
  461. X#endif
  462. X  if (pflag && dflag) 
  463. X    fprintf(stderr, "%s: p option can not be specified with d.\n", argv[0]);
  464. X  {
  465. X    char buf[80];
  466. X
  467. X    sprintf(buf, 
  468. X        "fired up by %s, timeout time is %d", getlogin(), timeouttime);
  469. X    syslog(LOG_INFO, buf);
  470. X  }
  471. X
  472. X  dumb = 0;
  473. X#ifndef HOSTNAME
  474. X  gethostname(hostname, 28);
  475. X#else
  476. X  strcpy(hostname, HOSTNAME);
  477. X#endif
  478. X  
  479. X  /** These are the terminals that this is compatible with.  If
  480. X   *  the invoker isn't on one of these, we define dumb, and
  481. X   *  skip all the frills.
  482. X   **/
  483. X  
  484. X  if (!dflag) {
  485. X    if (strncmp(term, "vt100", 5) && strncmp(term, "vt200", 5)
  486. X    && strncmp(term, "vt220", 5)  && strncmp(term, "vt240", 5) 
  487. X    && strncmp(term, "vt300", 5)  && strncmp(term, "hds220", 5)) dumb++;
  488. X  } else ++dumb;
  489. X
  490. X#ifdef TIMEOUT
  491. X  alarm(timeouttime*60);
  492. X  if (timeouttime)
  493. X    fprintf(stderr, "Timeout in %d minutes.\n", timeouttime);
  494. X  else
  495. X    fprintf(stderr, "The timeout has been disabled.\n", timeouttime);
  496. X  sleep(3);
  497. X#endif
  498. X  
  499. X  if ((pwd = getpwuid(getuid())) == NULL) 
  500. X    {     /** Not in passwd file.  Hmmm.  Funky.        **/
  501. X      assert(pwd == NULL);
  502. X      printf("Who the hell are you, and how did you manage that?\n");
  503. X      printf("[You don\'t appear to be in the passwd file.]\n");
  504. X      printf("Either your account has been deleted or your uid as been ");
  505. X      printf("munged.  [neat trick]\n");
  506. X      printf("You may want to contact your sysmgr.\n");
  507. X      exit(-1);
  508. X    }
  509. X  else 
  510. X    strcpy(myname, pwd->pw_name);
  511. X  
  512. X#ifndef dgux
  513. X  tag_utmp();
  514. X#endif
  515. X
  516. X  do_screen() ;
  517. X  
  518. X  if (!dumb)
  519. X    do {
  520. X      assert(!dumb);
  521. X      pid = fork ();
  522. X      switch (pid) {
  523. X      case -1: 
  524. X    assert(pid == -1);    /** This section hasn't been tested. **/
  525. X    fprintf(stderr, "\033[20;25HCan't fork... retrying...");
  526. X    pid = fork ();
  527. X    if (pid == 0)
  528. X      dodate (); /** Success **/
  529. X    break;
  530. X      case 0:  
  531. X    dodate ();      /** success **/
  532. X    /** NOT REACHED **/
  533. X    break;
  534. X      default:
  535. X    break;
  536. X      }
  537. X    } while (pid == -1);
  538. X  
  539. X  init_pwd ();
  540. X
  541. X  /** Loop until we get either the users password, or roots password **/
  542. X  for (;;) {   /**   Main body of program.  Loop until valid password **/
  543. X    char *passwd;
  544. X  kludge:
  545. X    if (!dumb)
  546. X      passwd = getpass ("\033[20;19H      Magic Word:\033[K ");
  547. X    else
  548. X      passwd = getpass ("Enter the magic word: ");
  549. X
  550. X    if (!strcmp(passwd, "credits")) {
  551. X      printcredits();
  552. X      goto kludge;
  553. X    } else
  554. X      if ((liberator = validate(passwd, &foo)) != NULL)
  555. X    break;
  556. X
  557. X    putchar(07);
  558. X    if (!dumb)
  559. X      printf("\033[20;19H            Nope.\033[K");
  560. X    else
  561. X      printf("Nope\n");
  562. X    fflush(stdout);
  563. X    sleep(2);
  564. X  }
  565. X  if (!dumb) {
  566. X    printf("\033[20;12HWelcome, %s, to this account%s.\033[J", liberator,
  567. X       foo ? ", Oh Mighty Wizard" : "");
  568. X    if (invalid)
  569. X      printf(
  570. X        "\033[21;6HThere were %d invalid attemps before this sucessful one.\n",
  571. X    invalid);
  572. X    printf("\n");
  573. X  } else {
  574. X    printf("\nWelcome, %s, to this account%s.\n", liberator,
  575. X       foo ? ", Oh Mighty Wizard" : "");
  576. X    if (invalid)
  577. X      printf("There were %d invalid before this sucessful one.\n", invalid);
  578. X}
  579. X
  580. X#ifndef dgux
  581. X  restore_utmp();
  582. X#endif
  583. X  
  584. X  if (!dumb)
  585. X    kill (pid,SIGTERM);  /** Kill our baby doing the time and date and load **/
  586. X
  587. X  fflush (stdout);
  588. X}
  589. X
  590. dodate () 
  591. X{
  592. X#ifdef TIMEOUT
  593. X  long foo[2];
  594. X#endif
  595. X#ifdef dgux
  596. X  char *obuf = (char *) malloc(80*5);
  597. X#endif
  598. X  char *tty = ttyname(0);
  599. X  int count = 0, update();
  600. X
  601. X  signal(SIGHUP, update);
  602. X  signal(SIGTERM, SIG_DFL);
  603. X  signal(SIGCONT, SIG_DFL);
  604. X
  605. X#ifndef dgux
  606. X  startup_time = time(0);
  607. X#else
  608. X  startup_time = time((long *)0);  /* wierd */
  609. X#endif
  610. X
  611. X#ifdef dgux
  612. X  setbuf(stdout, obuf);
  613. X#endif
  614. X
  615. X  if (timeouttime)
  616. X    --timeouttime;
  617. X
  618. X  nice(10);
  619. X  signal (SIGTERM, die);
  620. X  for (;;) {
  621. X    if (pflag) {                  /* Touch the terminal every soo often */
  622. X      foo[0] = foo[1] = time(0);
  623. X      utime(tty, foo);
  624. X    }
  625. X    if (++count > 5) {
  626. X      count = 0;
  627. X      do_screen();
  628. X    }
  629. X    
  630. X    if (timeouttime)
  631. X      printf("\033[17;25HTimeout in \033[1m%d\033[0m minutes.", timeouttime);
  632. X
  633. X    /** Have to put all this in one printf for DG/UX **/
  634. X    printf ("\033[22;24Hload: %.2f, and %d users.\033[K\033[23;18HStarted up at %26s\033[20;37H", load(), users(), ctime(&startup_time));
  635. X
  636. X    fflush (stdout);      /** Moves cursor to Password: prompt **/
  637. X    sleep (60);
  638. X    if (timeouttime)
  639. X      --timeouttime;
  640. X  }
  641. X}
  642. die () {
  643. X  exit (1);
  644. X}
  645. update () {
  646. X    if (timeouttime)
  647. X      printf("\033[17;25HTimeout in \033[1m%d\033[0m minutes.", timeouttime);
  648. X
  649. X    printf ("\033[22;24Hload: %.2f, and %d users.\033[K\033[23;18HStarted up at %26s\033[20;37H", load(), users(), ctime(&startup_time));
  650. X
  651. X    fflush (stdout);      /** Moves cursor to Password: prompt **/
  652. X    signal(SIGHUP, update);
  653. X}
  654. int Fkmem;
  655. int Futmp;
  656. static double avenrun[3];
  657. X
  658. static struct utmp buf;
  659. X
  660. static struct nlist nl[] = {
  661. X#define N_AVENRUN    0
  662. X#ifndef dgux
  663. X  { "_avenrun" },
  664. X#else
  665. X  { "avenrun" },
  666. X#endif
  667. X  { "" },
  668. X};
  669. X
  670. X/*
  671. X * load - Return the 5 minute load average
  672. X */
  673. double load()
  674. X{
  675. X  register i;
  676. X#ifdef dgux
  677. X  double lavg[3];
  678. X#endif
  679. X  
  680. X#if ns32000
  681. X  nlist("/dynix", nl);
  682. X#endif
  683. X#if dgux
  684. X  nlist("/dgux", nl);
  685. X#endif
  686. X#if defined(vax) || defined(pyr) || defined(sun)
  687. X  nlist("/vmunix", nl);
  688. X#endif
  689. X  
  690. X  if (nl[0].n_type == 0) return (-1);
  691. X  
  692. X  if ((Fkmem = open("/dev/kmem", 0)) < 0) return (-1);
  693. X  
  694. X  lseek(Fkmem, (long)nl[N_AVENRUN].n_value, 0);
  695. X#if ns32000
  696. X  {   long l_avenrun[3]; 
  697. X      read(Fkmem, l_avenrun, sizeof(l_avenrun));
  698. X      for (i=0; i < (sizeof(avenrun)/sizeof(avenrun[0])); i++) {
  699. X    avenrun[i] = ((double)l_avenrun[i])/1000.0;
  700. X      }
  701. X    }
  702. X#endif
  703. X#ifdef dgux
  704. X  lseek(Fkmem, (long)nl->n_value, 0);
  705. X  read(Fkmem, (char *)lavg, sizeof(lavg));
  706. X  avenrun[0] = lavg[0];
  707. X#endif
  708. X#if defined(vax) || defined(pyr) || defined(sun)
  709. X  read(Fkmem, avenrun, sizeof(avenrun));
  710. X#endif
  711. X  close(Fkmem);
  712. X  return (avenrun[0]);
  713. X}
  714. X
  715. X/*
  716. X * users - Count the number of users logged in.
  717. X */
  718. users()
  719. X{
  720. X#ifdef dgux
  721. X  struct utmp *ut;
  722. X#endif
  723. X  int count = 0;
  724. X  
  725. X  
  726. X  /* Get number of users */
  727. X#ifdef dgux
  728. X  setutent();
  729. X  while (ut = getutent()) if (ut->ut_type == USER_PROCESS) count++;
  730. X  endutent();
  731. X#else
  732. X  if ((Futmp = open("/etc/utmp", 0)) < 0) return (-1);
  733. X  
  734. X  (void) lseek(Futmp, (long)0, 0);
  735. X  while (read(Futmp, &buf, sizeof(buf)) > 0) {
  736. X    if (buf.ut_name[0] != '\0') {
  737. X      count++;
  738. X    }
  739. X  }
  740. X  close(Futmp);
  741. X#endif
  742. X  return (count);
  743. X}
  744. do_screen () {
  745. X  
  746. X  if (!dumb) {
  747. X    printf ("\033[H\033[2J\033(0\0331");    /** Clear screen, Graphics mode **/
  748. X    printf ("\
  749. X   lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk\n\
  750. X   x                                                                       x\n\
  751. X   x   ////////    //      //        ///     ///    ////////    /////////  x\n\
  752. X   x  aaaaaaaa/   aa/     aa/       aaa/    aaa/   aaaaaaaa/   aaaaaaaaa/  x\n\
  753. X   x     aa/      aaa/    aa/       aaa/    aaa/   aa/         aa/         x\n");
  754. X    printf("\
  755. X   x     aa/      aa/a/   aa/  ///  aaa/    aaa/   aa///////   aa//////    x\n\
  756. X   x     aa/      aa/ a/  aa/ aaa/  aaa/    aaa/   aaaaaaaa/   aaaaaaa/    x\n\
  757. X   x     aa/      aa/  a/ aa/       aaa/    aaa/         aa/   aa/         x\n\
  758. X   x   //aa////   aa/   a/aa/       aaa/////aaa/    /////aa/   aa////////  x\n");
  759. X    printf("\
  760. X   x  aaaaaaaa/   aa/    aaa/        aaaaaaaaa/    aaaaaaaa/   aaaaaaaaa/  x\n\
  761. X   x                                                                       x\n\
  762. X   mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj\n");
  763. X    
  764. X    printf ("\033(B\0332");
  765. X    printf ("\n\033[0m\033#3  This terminal is IN USE by \033[1m%s\033[0m\n", myname);
  766. X    printf ("\033[0m\033#4  This terminal is IN USE by \033[1m%s\033[0m\n", myname);
  767. X    printf ("\033#5");
  768. X    printf ("\n\n    Version %s for %s (%s)... Enter '\033[1mcredits\033[0m' for info on copyright\n", VERSION, 
  769. X#ifdef unix
  770. X        "Unix",
  771. X#else
  772. X        "VMS",        /** ICK!!!!! **/
  773. X#endif
  774. X        hostname);
  775. X    /**       Skip the @(#) junk in the banner             **/
  776. X    printf ("\033[16;0H         %s", (char *) (credits+4));
  777. X#ifdef UENT
  778. X    printf ("\033[24;0H                This terminal is in use by %s", muent.fullname);
  779. X#endif
  780. X    if (virgin == true) {
  781. X       assert(virgin == true);
  782. X       printf("\033[20;25HInitializing....");
  783. X       virgin = false;
  784. X    } else
  785. X       printf("\033[20;25HMagic Word:\033[K");     
  786. X  fflush(stdout);
  787. X  }
  788. X  else {     /* Less verbose... For terminals that can't do neat graphics.*/
  789. X#ifdef UENT
  790. X    printf("This terminal has been locked by %s\n", muent.fullname);
  791. X#endif
  792. X    printf("Terminal is LOCKED, RESERVED!\n");
  793. X    printf("NO TRESSPASSING.  BEWARE OF DOG.  NOBODY HOME.\n");
  794. X    printf("OUT TO LUNCH.  TRESSPASSERS WILL BE PROSECUTED.\n");
  795. X  }
  796. X  fflush(stdout);
  797. X}
  798. X/** Do the crypt.
  799. X **/
  800. char *mcrypt(arg1, arg2)
  801. char *arg1, *arg2;
  802. X{
  803. char *output;
  804. X
  805. X    output = CRYPT(arg1, arg2);
  806. X    return(output);
  807. X}
  808. X/** Is the a valid password?  Should I exit?  returns NULL if invalid attempt,
  809. X ** else returns a pointer to the name of the person who liberated the 
  810. X ** terminal.
  811. X **/
  812. char *validate(passwd, wiz) 
  813. register char *passwd; 
  814. register int *wiz;
  815. X{
  816. X  register struct unode *foo;
  817. X
  818. X  foo = wizusers;
  819. X
  820. X  *wiz = 1;
  821. X
  822. X  while (foo != NULL) {
  823. X    if (!strcmp(foo->passwd, mcrypt(passwd, foo->passwd))) {
  824. X      if (foo->next == NULL)
  825. X    *wiz = 0;
  826. X      return (foo->name);
  827. X    }
  828. X    foo = foo->next;
  829. X  }
  830. X  ++invalid;
  831. X  return(NULL);
  832. X}
  833. X/** Load crypted passwords into memory. 
  834. X **
  835. X ** If a ~user/.passwd file exists and is readable, we use that as
  836. X ** the encrypted password instead.
  837. X **/
  838. init_pwd () {
  839. X  struct passwd *hisent = NULL;
  840. X#ifdef WIZGROUP
  841. X  register g = 0;
  842. X  struct group *grp = NULL;
  843. X  struct unode *newone;
  844. X  char myname[9];
  845. X#endif
  846. X#ifdef UENT
  847. X  struct uent fooent;
  848. X#endif
  849. X
  850. X  assert(wizusers == NULL);  /** this has been initialized during
  851. X                   ** setup.  This must be false by definition 
  852. X                   **/
  853. X
  854. X  if ((hisent = getpwuid(getuid())) == NULL) 
  855. X    {
  856. X      printf("Who the hell are you?\n");
  857. X      exit(-1);
  858. X    }
  859. X  else {
  860. X    if ((wizusers = (struct unode *) malloc (sizeof(struct unode))) == NULL) {
  861. X      assert(wizusers = NULL);
  862. X      perror("malloc failed");
  863. X      kill(pid, SIGTERM);
  864. X      exit (-1);
  865. X    }
  866. X    strcpy(myname, hisent->pw_name);
  867. X#ifdef UENT
  868. X    fooent = getuent(hisent->pw_uid);
  869. X    strcpy(wizusers->name, fooent.fullname);
  870. X#else
  871. X    strcpy(wizusers->name, hisent->pw_name);
  872. X#endif
  873. X    wizusers->next = NULL;
  874. X
  875. X    { FILE *altpwf;
  876. X      char pwf[40];
  877. X
  878. X      sprintf(pwf, "%s/.passwd", hisent->pw_dir);
  879. X      if ((altpwf = fopen(pwf, "r")) == NULL)
  880. X    strcpy(wizusers->passwd, hisent->pw_passwd);
  881. X      else {
  882. X    fscanf(altpwf, "%s", wizusers->passwd);
  883. X    fclose(altpwf);
  884. X      }
  885. X    }
  886. X  }
  887. X
  888. X#ifdef WIZGROUP
  889. X  if ((grp = getgrnam(WIZGROUP)) != NULL) 
  890. X    while (grp->gr_mem[g] != NULL) {
  891. X      if (strcmp(grp->gr_mem[g], myname)) { /** Don't add me twice **/
  892. X    setpwent ();
  893. X    if ((hisent = getpwnam(grp->gr_mem[g++])) != NULL) {
  894. X      if ((newone=(struct unode *)malloc(sizeof(struct unode)))==NULL) {
  895. X        assert(newone == NULL);
  896. X        perror("malloc failed");
  897. X        kill(pid, SIGTERM);
  898. X        exit (-1);
  899. X      }
  900. X#ifdef UENT
  901. X      fooent = getuent(hisent->pw_uid);
  902. X      strcpy(newone->name, fooent.fullname);
  903. X#else
  904. X      strcpy(newone->name, hisent->pw_name);
  905. X#endif
  906. X      { FILE *altpwf;
  907. X        char pwf[40];
  908. X      
  909. X        sprintf(pwf, "%s/.passwd", hisent->pw_dir);
  910. X        if ((altpwf = fopen(pwf, "r")) == NULL)
  911. X          strcpy(newone->passwd, hisent->pw_passwd);
  912. X        else 
  913. X          {
  914. X        fscanf(altpwf, "%s", newone->passwd);
  915. X        fclose(altpwf);
  916. X          }
  917. X      }
  918. X      newone->next = wizusers;
  919. X      wizusers = newone;
  920. X      assert(wizusers != NULL);
  921. X      endpwent();
  922. X    }
  923. X      } else 
  924. X    g++;
  925. X    }    
  926. X#endif
  927. X}
  928. X#ifdef TIMEOUT
  929. X     
  930. X/**
  931. X ** This is called when the timeout time has been reached.
  932. X ** We log out the user by killing out Parent.... Lets hope
  933. X ** that that is the shell!
  934. X **/
  935. X
  936. timeout() 
  937. X{
  938. X  signal(SIGALRM, SIG_IGN);    /** Ignore anymore alarms... **/
  939. X  signal(SIGINT, SIG_IGN);    /** Just in case             **/
  940. X  signal(SIGQUIT, SIG_IGN);    /** Just in case             **/
  941. X
  942. X  kill(pid, SIGTERM);        /** Kill the baby doing the 
  943. X                 **  time and date.
  944. X                 **/
  945. X  if (!dumb)
  946. X    printf("\033[20;12HTimeout after %d minutes.\033[J\n\n", timeouttime);
  947. X  else
  948. X     printf("\nTimeout after %d minutes.\n", TIMEOUT);
  949. X
  950. X  fprintf(stderr, 
  951. X      "You have been idle for too long.  You are being TERMINATED....\n");
  952. X
  953. X  fflush(stdout);
  954. X  sleep(3);
  955. X  fprintf(stderr, ">>>>> ZAP <<<<<<,  You've been disintegrated.\n");
  956. X  ioctl(0, TIOCCDTR, 0);         /** Drop DTR                 **/
  957. X  kill(getppid(), SIGKILL);     /** Log me out              **/
  958. X  exit(-1);
  959. X}
  960. X#endif
  961. int wizuser() 
  962. X{
  963. X#ifdef WIZGROUP
  964. X  register i;                     /* index                      */
  965. X  char *group = WIZGROUP;         /* The name of the group      */
  966. X  struct group *gr;                 /* group file entry           */
  967. X  char *logname = (char *) getlogin ();  /* login name of caller       */
  968. X  gr = getgrnam(group);                  /* get id of authorized group */
  969. X
  970. X  if (gr == NULL) return(0);             /* groups does not exist      */
  971. X
  972. X  for (i = 0; gr->gr_mem[i] != NULL; i++)/* loop through each member   */
  973. X    if (!strcmp(gr->gr_mem[i], logname)) /* is he a valid member?      */
  974. X      return(1);                         /* user looks okay to me      */
  975. X#endif
  976. X  /** Or if we are the author, then we are a wiz user **/
  977. X  if (!strcmp(logname, "lavallee")) 
  978. X    return(1);
  979. X
  980. X  return(0);                             /* Not found                  */
  981. X}
  982. X
  983. X/** Change the guys passwd from the ~/.passwd file...  We return the new
  984. X ** crypted password if successful... NULL elsewise...  old is the
  985. X ** old crypted password.
  986. X **/
  987. X
  988. char *chpasswd(old)
  989. char *old;
  990. X{
  991. X    char saltc[2];
  992. X    long salt;
  993. X    int i;
  994. X    int c, pwlen;
  995. X    static char pwbuf[10];
  996. X    long time();
  997. X    char *mcrypt();
  998. X
  999. X    if (strlen(old) > 3) {
  1000. X      strcpy(pwbuf, getpass("Old password:"));
  1001. X      if (strcmp(old, mcrypt(pwbuf, old))) {
  1002. X        printf("Sorry\n");
  1003. X        exit(-1);
  1004. X      }
  1005. X    }
  1006. X
  1007. X    (void) strcpy(pwbuf, getpass("New password:"));
  1008. X    pwlen = strlen(pwbuf);
  1009. X    if (pwlen == 0) {
  1010. X        printf("Password unchanged.\n");
  1011. X        exit(-1);
  1012. X    }
  1013. X    /*
  1014. X     * Insure password is of reasonable length and
  1015. X     * composition.  If we really wanted to make things
  1016. X     * sticky, we could check the dictionary for common
  1017. X     * words, but then things would really be slow.
  1018. X     */
  1019. X    if (strcmp(pwbuf, getpass("Retype new password:")) != 0) {
  1020. X        printf("Mismatch - password unchanged.\n");
  1021. X        exit(-1);
  1022. X    }
  1023. X    (void) time(&salt);
  1024. X    salt = 9 * getpid();
  1025. X    saltc[0] = salt & 077;
  1026. X    saltc[1] = (salt>>6) & 077;
  1027. X    for (i = 0; i < 2; i++) {
  1028. X        c = saltc[i] + '.';
  1029. X        if (c > '9')
  1030. X            c += 7;
  1031. X        if (c > 'Z')
  1032. X            c += 6;
  1033. X        saltc[i] = c;
  1034. X    }
  1035. X    return(mcrypt(pwbuf, saltc));
  1036. X}
  1037. printcredits() 
  1038. X{
  1039. X  struct sgttyb buf, obuf;
  1040. X
  1041. X  gtty(0, &buf);
  1042. X  obuf = buf;
  1043. X  buf.sg_flags |= CBREAK;  /** Turn on cbreak **/
  1044. X  buf.sg_flags &= ~ECHO;   /** Turn off echo  **/
  1045. X  stty(0, &buf);
  1046. X
  1047. X  if (!dumb) 
  1048. X    kill(pid, SIGSTOP);  /** Don't want those stupid things on the screen **/
  1049. X  
  1050. X  fprintf(stderr, "\033[H\033[J");
  1051. X  fprintf(stderr, "Gone version %s. (c)1989 by %s\n",
  1052. X      VERSION, (authors+4));
  1053. X  fprintf(stderr, "\nIf you port this to any machines, context diffs would be greatly appreciated.\n");
  1054. X  fprintf(stderr, "The authors can be reached at 'lavallee@samsung.com, arosen@hawk.ulowell.edu'\n\n");
  1055. X  fprintf(stderr, "All rights reserved with the following \033[1mexceptions\033[0m:\n");
  1056. X  fprintf(stderr, "\n");
  1057. X  fprintf(stderr, "This software is supplied free of charge.  This software, or any part\n");
  1058. X  fprintf(stderr, "of it, may  not  be  redistributed or otherwise made available to, or\n");
  1059. X  fprintf(stderr, "used  by, any  other  person  without the inclusion of this copyright\n");
  1060. X  fprintf(stderr, "notice.  This software may not be used to make a profit in any way.\n");
  1061. X  fprintf(stderr, "\n");
  1062. X  fprintf(stderr, "This  software  is provided with absolutely no warranty, to the extent\n");
  1063. X  fprintf(stderr, "permitted  by  applicable  state law.  In no event, unless required by\n");
  1064. X  fprintf(stderr, "applicable law, will the author(s) of this this software be liable for\n");
  1065. X  fprintf(stderr, "any damages caused by this software.\n");
  1066. X  fprintf(stderr, "\n\n\n\n");
  1067. X  sleep(10);
  1068. X  do_screen();
  1069. X  if (!dumb) {
  1070. X    kill(pid, SIGCONT);
  1071. X    kill(pid, SIGHUP);
  1072. X  }
  1073. X  stty(0, &obuf);
  1074. X}
  1075. X
  1076. tag_utmp()
  1077. X{
  1078. X  struct utmp ut;
  1079. X  int slot = ttyslot();
  1080. X  int fd;
  1081. X
  1082. X  fd = open("/etc/utmp", O_RDWR);
  1083. X  if (fd == -1) {
  1084. X    return;
  1085. X  }
  1086. X  
  1087. X  if (lseek(fd, slot*(sizeof(ut)), L_SET) == -1) {
  1088. X    perror("utmp: lseek");
  1089. X    sleep(3);
  1090. X    return;
  1091. X  }
  1092. X  if (read(fd, &ut, sizeof(ut)) != sizeof(ut)) {
  1093. X    perror("utmp: read");
  1094. X    sleep(3);
  1095. X    return;
  1096. X  }
  1097. X  strcpy(savehost, ut.ut_host);
  1098. X  strcpy(ut.ut_host, "in gone");
  1099. X  if (lseek(fd, slot*(sizeof(ut)), L_SET) == -1) {
  1100. X    perror("utmp: lseek");
  1101. X    sleep(3);
  1102. X    return;
  1103. X  }
  1104. X  write(fd, &ut, sizeof(ut));
  1105. X  close(fd);
  1106. X}
  1107. X
  1108. restore_utmp()
  1109. X{
  1110. X  struct utmp ut;
  1111. X  int slot = ttyslot();
  1112. X  int fd;
  1113. X
  1114. X  fd = open("/etc/utmp", O_RDWR);
  1115. X  if (fd == -1) {
  1116. X    return;
  1117. X  }
  1118. X
  1119. X  assert(fd != -1);
  1120. X
  1121. X  if (lseek(fd, slot*(sizeof(ut)), L_SET) == -1) {
  1122. X    perror("utmp: lseek");
  1123. X    sleep(3);
  1124. X    return;
  1125. X  }
  1126. X  if (read(fd, &ut, sizeof(ut)) != sizeof(ut)) {
  1127. X    perror("utmp: read");
  1128. X    sleep(3);
  1129. X    return;
  1130. X  }
  1131. X  strcpy(ut.ut_host, savehost);
  1132. X  if (lseek(fd, slot*(sizeof(ut)), L_SET) == -1) {
  1133. X    perror("utmp: lseek");
  1134. X    sleep(3);
  1135. X    return;
  1136. X  }
  1137. X  write(fd, &ut, sizeof(ut));
  1138. X  close(fd);
  1139. X}
  1140. intprint(sig)
  1141. int sig;
  1142. X{
  1143. X  printf("\033[24;12HReceived a %d signal.", sig);
  1144. X  signal(signal, intprint);
  1145. X}
  1146. END_OF_FILE
  1147. if test 24387 -ne `wc -c <'gone.c'`; then
  1148.     echo shar: \"'gone.c'\" unpacked with wrong size!
  1149. fi
  1150. # end of 'gone.c'
  1151. fi
  1152. echo shar: End of archive 1 \(of 1\).
  1153. cp /dev/null ark1isdone
  1154. MISSING=""
  1155. for I in 1 ; do
  1156.     if test ! -f ark${I}isdone ; then
  1157.     MISSING="${MISSING} ${I}"
  1158.     fi
  1159. done
  1160. if test "${MISSING}" = "" ; then
  1161.     echo You have the archive.
  1162.     rm -f ark[1-9]isdone
  1163. else
  1164.     echo You still need to unpack the following archives:
  1165.     echo "        " ${MISSING}
  1166. fi
  1167. ##  End of shell archive.
  1168. exit 0
  1169. -- 
  1170. INTERNET:  lavallee@samsung.com
  1171. UUCP:      {decvax!{gsg,cg-atla},uunet,ulowell}!ginosko!lavallee
  1172. US MAIL:   Samsung Software America. One Corporate Dr.  Andover, Ma.  01810
  1173.